/*******************************************************************************
  * 文件：DevInfor.h
  * 作者：djy
  * 版本：v1.0.0
  * 日期：2020-12-05
  * 说明：设备信息
*******************************************************************************/
#include "DevInfor.h"
#include "OS_Task.h"
#include "Hardware_ADC.h"
#include "Hardware_IO.h"
#include "DisplayBoard.h"
#include "FireCtrl.h"
#include "DevError.h"
#include "StateMachine.h"
#include "NetComm_Message.h"
#include "main.h"
#include <string.h>

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
//设备U+协议版本、SoftAP名称、typeID
static const char DevUPlusVer[] = "E++2.17";
static const char DevSoftAP[]   = "U-CU";
static const U8   DevTypeID[]   = {0x20,0x1c,0x10,0xc7,0x14,0x12,0x02,0x10,
                                   0x1d,0x01,0x5f,0x58,0x71,0xad,0xd2,0x00,
                                   0x00,0x00,0x31,0x6f,0xa3,0xe7,0xae,0xd4,
                                   0x7a,0x0f,0xbc,0x45,0xd0,0x42,0x4f,0x40};
static DevInfor_ts sDevInfor;
static Timer_ts sPowerDetectTimer;
/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：Dev_GetUPlusVer
  * 功  能：获取U+协议版本
  * 参  数：协议版本字符串存储目的地址
  * 返回值:"E++2.17"字符串长度
  * 说  明：E++2.17
*******************************************************************************/
U8  Dev_GetUPlusVer(void *Ver)
{
    strcpy(Ver,DevUPlusVer);
    return strlen(DevUPlusVer);
}

/*******************************************************************************
  * 函数名：Dev_GetSoftAP
  * 功  能：获取SoftAP
  * 参  数："U-CU"字符串存储目的地址
  * 返回值:"U-CU"字符串长度
  * 说  明："U-CU"
*******************************************************************************/
U8 Dev_GetSoftAP(void *SoftAP)
{
    strcpy(SoftAP,DevSoftAP);
    return strlen(DevSoftAP);
}

/*******************************************************************************
  * 函数名：Dev_GetSoftAP
  * 功  能：获取TypeID
  * 参  数：TypeID存储目的地址
  * 返回值:TypeID长度
  * 说  明：TypeID
*******************************************************************************/
U8 Dev_GetTypeID(void *TypeID)
{
    memcpy(TypeID,DevTypeID,sizeof(DevTypeID));
    return sizeof(DevTypeID);
}

/*******************************************************************************
  * 函数名：Dev_SetLeftFireState
  * 功  能：设置左灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Dev_SetLeftFireState(FireState_te eState)
{
	sDevInfor.eLeftFireState = eState;  
}

/*******************************************************************************
  * 函数名：Dev_SetMidFireState
  * 功  能：设置中灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Dev_SetMidFireState(FireState_te eState)
{
	sDevInfor.eMidFireState = eState;  
}

/*******************************************************************************
  * 函数名：Dev_SetRightFireState
  * 功  能：设置右灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Dev_SetRightFireState(FireState_te eState)
{
    sDevInfor.eRightFireState = eState;
}

/*******************************************************************************
  * 函数名：Dev_GetLeftFireState
  * 功  能：获取左灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
FireState_te Dev_GetLeftFireState(void)
{
    return sDevInfor.eLeftFireState;
}

/*******************************************************************************
  * 函数名：Dev_GetMidFireState
  * 功  能：获取中灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
FireState_te Dev_GetMidFireState(void)
{
    return sDevInfor.eMidFireState;
}

/*******************************************************************************
  * 函数名：Dev_GetRightFireState
  * 功  能：获取右灶火状态
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
FireState_te Dev_GetRightFireState(void)
{
    return sDevInfor.eRightFireState;
}

/*******************************************************************************
  * 函数名：Dev_GetDevType
  * 功  能：获取设备类型
  * 参  数：无
  * 返回值：无
  * 说  明：上电后需要检测显示板与wifi板类型，以区分是C6还是C3设备
*******************************************************************************/
DevType_te Dev_GetDevType(void)
{
    return sDevInfor.eDevType;
}

/*******************************************************************************
  * 函数名：Dev_SetDevType
  * 功  能：设置设备类型
  * 参  数：无
  * 返回值：无
  * 说  明：上电后需要检测显示板与wifi板类型，以区分是C6还是C3设备
*******************************************************************************/
void Dev_SetDevType(DevType_te eDevType)
{
    sDevInfor.eDevType = eDevType;
}

/*******************************************************************************
  * 函数名：Dev_SetPowerState
  * 功  能：设置电源状态
  * 参  数：无
  * 返回值：无
  * 说  明：上电后ADC检测VDD,VDD>3V,认为电源已上电
*******************************************************************************/
void Dev_SetPowerState(Bool bState)
{
    sDevInfor.bPowerState = bState;
}

/*******************************************************************************
  * 函数名：Dev_GetPowerState
  * 功  能：获取电源状态
  * 参  数：无
  * 返回值：无
  * 说  明：上电后ADC检测VDD,VDD>3V,认为电源已上电
*******************************************************************************/
Bool Dev_GetPowerState(void)
{
    return sDevInfor.bPowerState;
}

/*******************************************************************************
  * 函数名：Dev_CheckDemoModeFlag
  * 功  能：检测演示模式标志位
  * 参  数：无
  * 返回值：Bool bFlag：演示模式标志位
  * 说  明：未点火时，长按任意按键十秒钟，进入演示模式
*******************************************************************************/
Bool Dev_CheckDemoModeFlag(void)
{
    return sDevInfor.bDemoMode; 
}

/*******************************************************************************
  * 函数名：Dev_SetDemoModeFlag
  * 功  能：设置演示模式标志位
  * 参  数：Bool bFlag：演示模式标志位
  * 返回值：无
  * 说  明：未点火时，长按任意按键十秒钟，进入演示模式
*******************************************************************************/
void Dev_SetDemoModeFlag(Bool bFlag)
{
    sDevInfor.bDemoMode = bFlag;
}

/*******************************************************************************
  * 函数名：DevInfor_ADCCheckTask
  * 功  能：ADC检测
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
static void DevInfor_ADCCheckTask(void)
{	
	// 检查左灶关火标志位
	if(TRUE == CheckLeftFireOffFlag())
	{
	  	// 已关火，灶火关闭
        Dev_SetLeftFireState(eFIRE_OFF);
	}
	else
	{	
	    if(FALSE == CheckInFireOnPeriod()
		   	&& FALSE == CheckInFireOffPeriod())
	    {
	        // 不在点火周期，也不在关火周期，方可检测热电偶
    		if(Hardware_GetLeftRDO() > U16_RDO_FIRE_STATE_THRESHOLD)
    		{
    			// 灶火已开
    			Dev_SetLeftFireState(eFIRE_ON);
    		}
    		else
    		{
    			// 灶火关闭
    			Dev_SetLeftFireState(eFIRE_OFF);
    		}
	    }
	}

    static  U16 u16RightRDO;
    
    u16RightRDO = Hardware_GetRightRDO();
    
	// 检查右灶关火标志位
	if(TRUE == CheckRightFireOffFlag())
	{
	  	// 已关火，灶火关闭
        Dev_SetRightFireState(eFIRE_OFF);
	}
	else
	{
	  	if(FALSE == CheckInFireOnPeriod()
		   	&& FALSE == CheckInFireOffPeriod())
	    {
	      	// 不在点火周期，也不在关火周期，方可检测热电偶
    		if(u16RightRDO > U16_RDO_FIRE_STATE_THRESHOLD)
    		{
    			// 灶火已开
    			Dev_SetRightFireState(eFIRE_ON);
    		}
    		else
    		{
    			// 灶火关闭
    			Dev_SetRightFireState(eFIRE_OFF);
    		}  
	    }
	}
	
	// 检查中灶关火标志位
	if(TRUE == CheckMidFireOffFlag())
	{
	  	// 已关火，灶火关闭
        Dev_SetMidFireState(eFIRE_OFF);
	}
	else
	{
	   	if(FALSE == CheckInFireOnPeriod()
		   	&& FALSE == CheckInFireOffPeriod())
	    { 
    	  	// 不在点火周期，也不在关火周期，方可检测热电偶
    		if(Hardware_GetMidRDO() > U16_RDO_FIRE_STATE_THRESHOLD)
    		{
    			// 灶火已开
    			Dev_SetMidFireState(eFIRE_ON);
    		}
    		else
    		{
    			// 灶火关闭
    			Dev_SetMidFireState(eFIRE_OFF);
    		}	    
		}
	}
}

/*******************************************************************************
  * 函数名：FXQCheckTask
  * 功  能：副线圈检测
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
static void DevInfor_FXQCheckTask(void)
{
    if(TRUE == CheckInFireOnPeriod() || TRUE == CheckInFireOffPeriod())
    {
        // 在点火周期或关火周期，提前退出，不检测副线圈
        return;
    }

    // 检测左灶副线圈是否异常：副线圈返回高电平，且不在演示和故障模式，且旋钮开关闭合
    if(ON == Hardware_LeftStoveFXQCheck()
        && eDEV_ERROR != StateMachine_GetCurState()
            && FALSE == Dev_CheckDemoModeFlag()
                && 0 == Hardware_LeftStoveKnobCheck())
    {
        // 设置故障类型
        Dev_SetErrorType(eERR_LEFT,eERR_FXQ);
        // 切换到故障模式
        StateMachine_Change(eDEV_ERROR);
    }
    else if(OFF == Hardware_LeftStoveFXQCheck()
            && eDEV_ERROR == StateMachine_GetCurState()
                && eERR_LEFT == Dev_GetErrorPos()
                    && eERR_FXQ == Dev_GetErrorType())
    {
        // 左副线圈恢复正常，退出故障模式
        DevErrorExit();
    }

    // 检测中灶副线圈是否异常：副线圈返回高电平，且不在演示和故障模式，且旋钮开关闭合
    if(ON == Hardware_MidStoveFXQCheck()
        && eDEV_ERROR != StateMachine_GetCurState()
           && FALSE == Dev_CheckDemoModeFlag()
                && 0 == Hardware_MidStoveKnobCheck())
    {
        // 设置故障类型
        Dev_SetErrorType(eERR_MID,eERR_FXQ);
        // 切换到故障模式
        StateMachine_Change(eDEV_ERROR);
    }
    else if(OFF == Hardware_MidStoveFXQCheck()
            && eDEV_ERROR == StateMachine_GetCurState()
                && eERR_MID == Dev_GetErrorPos()
                    && eERR_FXQ == Dev_GetErrorType())
    {
        // 中副线圈恢复正常，退出故障模式
        DevErrorExit();
    }

    // 检测右灶副线圈是否异常：副线圈返回高电平，且不在演示和故障模式，且旋钮开关闭合
    if(ON == Hardware_RightStoveFXQCheck()
        && eDEV_ERROR != StateMachine_GetCurState()
           && FALSE == Dev_CheckDemoModeFlag()
                && 0 == Hardware_RightStoveKnobCheck())
    {
        // 设置故障类型
        Dev_SetErrorType(eERR_RIGHT,eERR_FXQ);
        // 切换到故障模式
        StateMachine_Change(eDEV_ERROR);
    }
    else if(OFF == Hardware_RightStoveFXQCheck()
            && eDEV_ERROR == StateMachine_GetCurState()
                && eERR_RIGHT == Dev_GetErrorPos()
                    && eERR_FXQ == Dev_GetErrorType())
    {
        // 右副线圈恢复正常，退出故障模式
        DevErrorExit();
    }
}

static void PowerCheckHook_1MS(void)
{
  	static U16 u16PowerADC;
	
	// 若在关火周期，不进行电源电压检测（关火时会将电源电压拉低到3V以下）
	if(TRUE == CheckInFireOffPeriod())
	{
		return;
	}
	
	// 获取电源电压
	u16PowerADC = Hardware_GetVDDResult();
	
    // 检测电源状态
    if(u16PowerADC > 426)
    {
        // VDD大于3V，电源开启
        Dev_SetPowerState(ON);

        // 若当前报电压故障，退出故障
        if(eDEV_ERROR == StateMachine_GetCurState()
            && eERR_ALL == Dev_GetErrorPos()
                && eERR_VOLTAGE == Dev_GetErrorType())
        {
            // 退出故障
            DevErrorExit();            
        }
		
		OS_TimerClearExpiredTimes(&sPowerDetectTimer);
    }
    else
    {
	  	 // 电压下降超过5毫秒，滤掉杂波
	  	if(OS_TimerGetExpiredTimes(&sPowerDetectTimer) >= 5)
		{
			// VDD从3V降至小于3V，且不在演示模式
			if(ON == Dev_GetPowerState() && FALSE == Dev_CheckDemoModeFlag())
			{
				Dev_SetErrorType(eERR_ALL,eERR_VOLTAGE);
				StateMachine_Change(eDEV_ERROR);
			}

			// VDD小于3V，电源关闭
			Dev_SetPowerState(OFF);
			
			OS_TimerClearExpiredTimes(&sPowerDetectTimer);
		}
    }	
}

/*******************************************************************************
  * 函数名：DevInfor_StoveRangeHoodLinkTask
  * 功  能：烟灶联动检测
  * 参  数：无
  * 返回值：无
  * 说  明：任意旋钮开关打开，即开启烟灶联动
*******************************************************************************/
static void DevInfor_StoveRangeHoodLinkTask(void)
{
    // 检测旋钮开关闭合
    if(0 == Hardware_LeftStoveKnobCheck() 
        || 0 == Hardware_MidStoveKnobCheck()
          || 0 == Hardware_RightStoveKnobCheck())
    {
        // 任意旋钮开关闭合，开启联动
        Hardware_StoveRangeHoodLink(0);
    }
    else
    {
        // 旋钮开关全部闭合，关闭联动
        Hardware_StoveRangeHoodLink(1);
    }
}

/*******************************************************************************
  * 函数名：Dev_Init
  * 功  能：设备信息初始化
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Dev_Init(void)
{
    // memset(&sDevInfor,0x00,sizeof(sDevInfor));

  	// 启动电源检测任务
    OS_TimerStart(&sPowerDetectTimer,1,PowerCheckHook_1MS);
  
    OS_TaskCreate(DevInfor_ADCCheckTask);// 启动ADC转换任务
    OS_TaskCreate(DevInfor_FXQCheckTask);// 启动副线圈检测任务
    OS_TaskCreate(DevInfor_StoveRangeHoodLinkTask);// 启动烟机联动任务
}

